package cg.cmm.base.intercept;

import cg.cmm.base.constant.Constant;
import cg.cmm.base.utils.RequestIdUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.MimeHeaders;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @author wangchong
 * @description 拦截器
 * 在请求之前进行拦截，获取请求头中的TRACE_ID 判断是否为空
 * 1.如果为空 新生成TRACE_ID放到请求头中
 * 2.如果不为空 则以当前请求头中的TRACE_ID走完整个请求
 * 使用：将TraceID放入请求头中 .addHeader(Constant.TRACE_ID, RequestIdUtil.getRequestId())
 * @date 2024/1/29 13:25
 */
@Slf4j
public class TraceIdInterceptor implements HandlerInterceptor {
    /**
     * @return boolean
     * @description 在请求之前执行
     * @date 2024/1/29 13:26
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("------------------Into TraceIdInterceptor preHandle------------------");
        String requestId = request.getHeader(Constant.TRACE_ID);
        if (StringUtils.isBlank(requestId)) {
            RequestIdUtils.setRequestId();
            String traceId = RequestIdUtils.getRequestId();
            Map<String, String> map = new HashMap<>();
            map.put(Constant.TRACE_ID, traceId);
            // 将TraceID放入请求头中
            addHeader(request, map);
        } else {
            RequestIdUtils.setRequestId(requestId);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    /**
     * @return boolean
     * @description TRACE_ID清除
     * @date 2024/1/29 13:26
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        RequestIdUtils.clear();
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    /**
     * @param request:
     * @param headerMap: 请求头中的参数
     * @return void
     * @description 将数据放到请求头中
     * @date 2024/1/29 13:26
     */
    private void addHeader(HttpServletRequest request, Map<String, String> headerMap) {
        if (headerMap == null || headerMap.isEmpty()) {
            return;
        }
        Class<? extends HttpServletRequest> c = request.getClass();
        try {
            Field requestField = c.getDeclaredField("request");
            requestField.setAccessible(true);
            Object o = requestField.get(request);
            Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
            coyoteRequest.setAccessible(true);
            Object o2 = coyoteRequest.get(o);
            Field headers = o2.getClass().getDeclaredField("headers");
            headers.setAccessible(true);
            MimeHeaders mimeHeaders = (MimeHeaders) headers.get(o2);
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                mimeHeaders.removeHeader(entry.getKey());
                mimeHeaders.addValue(entry.getKey()).setString(entry.getValue());
            }
        } catch (Exception e) {
            log.error("请求头异常日志:{}", e.getMessage());
        }
    }
}